package com.powerbank.admin.service.impl;

import cn.hutool.crypto.digest.BCrypt;
import com.powerbank.admin.dto.AdminLoginDTO;
import com.powerbank.admin.service.AdminAuthService;
import com.powerbank.admin.vo.AdminLoginVO;
import com.powerbank.admin.vo.AdminMenuVO;
import com.powerbank.admin.vo.AdminRoleVO;
import com.powerbank.common.exception.BusinessException;
import com.powerbank.common.result.ResultCode;
import com.powerbank.common.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 管理员认证服务实现类（简化版）
 */
@Slf4j
@Service
public class AdminAuthServiceImpl implements AdminAuthService {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 演示用的管理员账号，实际项目中应该从数据库查询
    private static final String DEMO_USERNAME = "admin";
    private static final String DEMO_PASSWORD = "$2a$10$7JB720yubVSuIWl7ER1JQOjRkKqRfKn.QfJKVuKqNKZVuOL3nN7lm"; // 密码：123456

    @Override
    public AdminLoginVO login(AdminLoginDTO loginDTO) {
        log.info("管理员登录 - 用户名: {}", loginDTO.getUsername());

        // 1. 验证用户名和密码（简化版，实际应该查询数据库）
        if (!DEMO_USERNAME.equals(loginDTO.getUsername())) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }

        if (!BCrypt.checkpw(loginDTO.getPassword(), DEMO_PASSWORD)) {
            throw new BusinessException(ResultCode.PASSWORD_ERROR);
        }

        // 2. 生成Token
        Long adminId = 1L; // 演示管理员ID
        String accessToken = jwtUtils.generateToken(adminId, DEMO_USERNAME, "admin");
        String refreshToken = jwtUtils.generateToken(adminId, DEMO_USERNAME, "admin");

        // 3. 缓存Token信息
        String tokenKey = "admin:token:" + adminId;
        redisTemplate.opsForValue().set(tokenKey, accessToken, 8, TimeUnit.HOURS);

        // 4. 构建返回结果
        AdminLoginVO result = new AdminLoginVO();
        result.setAdminId(adminId);
        result.setUsername(loginDTO.getUsername());
        result.setRealName("系统管理员");
        result.setEmail("admin@powerbank.com");
        result.setPhone("13800138000");
        result.setAccessToken(accessToken);
        result.setRefreshToken(refreshToken);
        result.setExpireTime(LocalDateTime.now().plusHours(8));
        result.setLastLoginTime(LocalDateTime.now());
        result.setLastLoginIp(loginDTO.getClientIp());

        // 5. 设置角色和权限（演示数据）
        result.setRoles(getDemoRoles());
        result.setPermissions(getDemoPermissions());
        result.setMenus(getDemoMenus());

        log.info("管理员{}登录成功", loginDTO.getUsername());
        return result;
    }

    @Override
    public boolean logout(String token) {
        try {
            if (token.startsWith("Bearer ")) {
                token = token.substring(7);
            }

            Long adminId = jwtUtils.getUserIdFromToken(token);
            String tokenKey = "admin:token:" + adminId;
            redisTemplate.delete(tokenKey);

            log.info("管理员{}登出成功", adminId);
            return true;
        } catch (Exception e) {
            log.error("管理员登出失败", e);
            return false;
        }
    }

    @Override
    public AdminLoginVO refreshToken(String token) {
        if (token.startsWith("Bearer ")) {
            token = token.substring(7);
        }

        Long adminId = jwtUtils.getUserIdFromToken(token);
        
        // 生成新Token
        String newAccessToken = jwtUtils.generateToken(adminId, DEMO_USERNAME, "admin");
        String newRefreshToken = jwtUtils.generateToken(adminId, DEMO_USERNAME, "admin");

        // 更新缓存
        String tokenKey = "admin:token:" + adminId;
        redisTemplate.opsForValue().set(tokenKey, newAccessToken, 8, TimeUnit.HOURS);

        AdminLoginVO result = new AdminLoginVO();
        result.setAdminId(adminId);
        result.setUsername(DEMO_USERNAME);
        result.setAccessToken(newAccessToken);
        result.setRefreshToken(newRefreshToken);
        result.setExpireTime(LocalDateTime.now().plusHours(8));

        return result;
    }

    @Override
    public AdminLoginVO getCurrentAdminInfo(String token) {
        if (token.startsWith("Bearer ")) {
            token = token.substring(7);
        }

        Long adminId = jwtUtils.getUserIdFromToken(token);
        
        // 验证Token是否在缓存中
        String tokenKey = "admin:token:" + adminId;
        String cachedToken = (String) redisTemplate.opsForValue().get(tokenKey);
        if (cachedToken == null || !cachedToken.equals(token)) {
            throw new BusinessException(ResultCode.TOKEN_INVALID);
        }

        AdminLoginVO result = new AdminLoginVO();
        result.setAdminId(adminId);
        result.setUsername(DEMO_USERNAME);
        result.setRealName("系统管理员");
        result.setEmail("admin@powerbank.com");
        result.setPhone("13800138000");
        result.setRoles(getDemoRoles());
        result.setPermissions(getDemoPermissions());
        result.setMenus(getDemoMenus());

        return result;
    }

    @Override
    public Long validateTokenAndGetAdminId(String token) {
        if (token.startsWith("Bearer ")) {
            token = token.substring(7);
        }

        Long adminId = jwtUtils.getUserIdFromToken(token);
        
        // 验证Token是否在缓存中
        String tokenKey = "admin:token:" + adminId;
        String cachedToken = (String) redisTemplate.opsForValue().get(tokenKey);
        if (cachedToken == null || !cachedToken.equals(token)) {
            throw new BusinessException(ResultCode.TOKEN_INVALID);
        }

        return adminId;
    }

    @Override
    public boolean hasPermission(Long adminId, String permission) {
        // 简化版：超级管理员拥有所有权限
        if (adminId.equals(1L)) {
            return true;
        }

        // 实际项目中应该查询数据库
        List<String> permissions = getDemoPermissions();
        return permissions.contains(permission);
    }

    /**
     * 获取演示角色数据
     */
    private List<AdminRoleVO> getDemoRoles() {
        AdminRoleVO role = new AdminRoleVO();
        role.setRoleId(1L);
        role.setRoleCode("SUPER_ADMIN");
        role.setRoleName("超级管理员");
        role.setRoleDesc("系统超级管理员，拥有所有权限");
        role.setRoleType("SYSTEM");
        role.setRoleStatus(1);

        List<AdminRoleVO> roles = new ArrayList<>();
        roles.add(role);
        return roles;
    }

    /**
     * 获取演示权限数据
     */
    private List<String> getDemoPermissions() {
        return Arrays.asList(
                "system:user:list", "system:user:add", "system:user:edit", "system:user:delete",
                "system:role:list", "system:role:add", "system:role:edit", "system:role:delete",
                "system:menu:list", "system:menu:add", "system:menu:edit", "system:menu:delete",
                "business:user:list", "business:user:view", "business:user:edit",
                "business:device:list", "business:device:add", "business:device:edit", "business:device:delete",
                "business:order:list", "business:order:view", "business:order:edit",
                "business:finance:list", "business:finance:view", "business:finance:export"
        );
    }

    /**
     * 获取演示菜单数据
     */
    private List<AdminMenuVO> getDemoMenus() {
        List<AdminMenuVO> menus = new ArrayList<>();

        // 系统管理
        AdminMenuVO systemMenu = new AdminMenuVO();
        systemMenu.setMenuId(1L);
        systemMenu.setParentId(0L);
        systemMenu.setMenuName("系统管理");
        systemMenu.setMenuPath("/system");
        systemMenu.setMenuIcon("setting");
        systemMenu.setMenuType("MENU");
        systemMenu.setSortOrder(1);
        systemMenu.setVisible(1);

        List<AdminMenuVO> systemChildren = new ArrayList<>();
        
        AdminMenuVO userMenu = new AdminMenuVO();
        userMenu.setMenuId(11L);
        userMenu.setParentId(1L);
        userMenu.setMenuName("用户管理");
        userMenu.setMenuPath("/system/user");
        userMenu.setMenuIcon("user");
        userMenu.setMenuType("MENU");
        userMenu.setPermission("system:user:list");
        userMenu.setSortOrder(1);
        userMenu.setVisible(1);
        systemChildren.add(userMenu);

        AdminMenuVO roleMenu = new AdminMenuVO();
        roleMenu.setMenuId(12L);
        roleMenu.setParentId(1L);
        roleMenu.setMenuName("角色管理");
        roleMenu.setMenuPath("/system/role");
        roleMenu.setMenuIcon("team");
        roleMenu.setMenuType("MENU");
        roleMenu.setPermission("system:role:list");
        roleMenu.setSortOrder(2);
        roleMenu.setVisible(1);
        systemChildren.add(roleMenu);

        systemMenu.setChildren(systemChildren);
        menus.add(systemMenu);

        // 业务管理
        AdminMenuVO businessMenu = new AdminMenuVO();
        businessMenu.setMenuId(2L);
        businessMenu.setParentId(0L);
        businessMenu.setMenuName("业务管理");
        businessMenu.setMenuPath("/business");
        businessMenu.setMenuIcon("shop");
        businessMenu.setMenuType("MENU");
        businessMenu.setSortOrder(2);
        businessMenu.setVisible(1);

        List<AdminMenuVO> businessChildren = new ArrayList<>();
        
        AdminMenuVO deviceMenu = new AdminMenuVO();
        deviceMenu.setMenuId(21L);
        deviceMenu.setParentId(2L);
        deviceMenu.setMenuName("设备管理");
        deviceMenu.setMenuPath("/business/device");
        deviceMenu.setMenuIcon("laptop");
        deviceMenu.setMenuType("MENU");
        deviceMenu.setPermission("business:device:list");
        deviceMenu.setSortOrder(1);
        deviceMenu.setVisible(1);
        businessChildren.add(deviceMenu);

        AdminMenuVO orderMenu = new AdminMenuVO();
        orderMenu.setMenuId(22L);
        orderMenu.setParentId(2L);
        orderMenu.setMenuName("订单管理");
        orderMenu.setMenuPath("/business/order");
        orderMenu.setMenuIcon("file-text");
        orderMenu.setMenuType("MENU");
        orderMenu.setPermission("business:order:list");
        orderMenu.setSortOrder(2);
        orderMenu.setVisible(1);
        businessChildren.add(orderMenu);

        businessMenu.setChildren(businessChildren);
        menus.add(businessMenu);

        return menus;
    }
}